﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Core.Base;
using ERP.BusinessEntities;
using System.Windows.Forms;
using System.Data;
using System.Data.Linq.Mapping;
using ERP.DAL;
using Core.Component;
using ERP.BusinessEntities.Base;
using ERP.BusinessEntities.Factory;
using Base;
using Components;
using ERP.BusinessEntities.Util;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;

namespace Core
{
    public class AppContext
    {
        #region Constant
        public const String cstFirstControlTag = "FIRST";
        public const String cstGridViewItems = "ITEM";

        public const String cstMainItemPrefix = "Item";

        public const String cstEmptyNo = "*NEW*";
        public const String cstUnknowNo = "*Unknow*";

        public const String cstConstTableName = "BSConsts";
        public const String cstConstKey = "Key";
        public const String cstConstValue = "Value";

        public const String cstcontrolTagClose = "CLOSE";
        public const String cstcontrolTagExit= "EXIT";

        #endregion

        #region Field Constant

        public const String cstID = "ID";
        public const String cstNo = "No";
        public const String cstName = "Name";
        public const String cstDesc= "Dsc";

        public const String cstCreatedUser = "CreatedUser";
        public const String cstCreatedDate = "CreatedDate";
        public const String cstUpdatedUser = "UpdatedUser"; 
        public const String cstUpdatedDate = "UpdatedDate"; 

        public const String cstFK_Currency = "FK_GECurrencys_ID";
        public const String cstExcRate = "ExcRate";

        public const String cstUOMRate = "UOMRate";
        public const String cstFQty = "FQty";
        public const String cstQty = "Qty";

        public const String cstFUnitPrice = "FUnitPrice";
        public const String cstUnitPrice = "UnitPrice";

        public const String cstFPrice = "FPrice";
        public const String cstPrice = "Price";

        public const String cstFDiscAmt = "FDiscAmt";
        public const String cstDiscAmt = "DiscAmt";

        public const String cstFNetAmt = "FNetAmt";
        public const String cstNetAmt = "NetAmt";

        public const String cstFTaxAmt = "FTaxAmt";
        public const String cstTaxAmt = "TaxAmt";

        public const String cstFAmt = "FAmt";
        public const String cstAmt = "Amt";

        public const String cstFKTaxCode = "FK_TxTaxCodes_ID";
        public const String cstTaxPct = "TaxPct";

        public const String cstFKStock = "FK_ICStocks_ID";
        public const String cstFKProduct = "FK_ICProducts_ID";
        public const String cstFKStockUOM = "FK_ICStockUOMs_ID";

        #endregion

        public static BSCompanysInfo CurrentCompanyInfo;
        public static BSUsersInfo CurrentUserInfo;
        public static Form MainAppForm;
        public static Dictionary<String, Type> dicModuleTypes = new Dictionary<string, Type>();

        public static Dictionary<String, DataTable> dicDataSources = new Dictionary<string, DataTable>();

        public static ToolStripProgressBar ProgresBar;

        public static Image DrillIcon;
        public static Image LookUpIcon;

        #region Controller
        public static BSStartupModulesController StartUpModuleCtrl = new BSStartupModulesController();
        public static BSCompanysController CompanyCtrl = new BSCompanysController();
        public static BSDatesController DateCtrl = new BSDatesController();
        public static ICProductUOMsController ProductUOMCtrl = new ICProductUOMsController();
        public static BSNumberConfigsController NumberCfgCtrl = new BSNumberConfigsController();
        public static ICStockUOMsController StockUOMCtrl = new ICStockUOMsController();
        public static GECurrencysController CurrencyCtrl = new GECurrencysController();
        public static TxTaxCodesController TaxCodeCtrl = new TxTaxCodesController();
        public static ICProductsController ProductCtrl = new ICProductsController();
        public static ICInvStocksController InvStockCtrl = new ICInvStocksController();
        public static ICInvStockItemsController InvStockItemCtrl = new ICInvStockItemsController();
        public static ICShipmentItemsController ShipmentItemCtrl = new ICShipmentItemsController();
        public static BSConstsController ConstCtrl = new BSConstsController();
        public static ICReceiptsController ReceiptCtrl = new ICReceiptsController();
        public static ICReceiptItemsController ReceiptItemCtrl = new ICReceiptItemsController();
        public static GLBPsController BPCtrl = new GLBPsController();
        public static GLBPSectorsController BPSectorCtrl = new GLBPSectorsController();
        public static ARSOsController SOCtrl = new ARSOsController();
        public static ARSOItemsController SOItemCtrl = new ARSOItemsController();
        public static APPOsController POCtrl = new APPOsController();
        public static APPOItemsController POItemCtrl = new APPOItemsController();
        public static BSObjectLocksController ObjectLockCtrl = new BSObjectLocksController();
        public static ICTransfersController TransferCtrl = new ICTransfersController();
        public static ICTransferItemsController TransferItemCtrl = new ICTransferItemsController();
        public static BSModuleMapingsController ModuleMapingCtrl = new BSModuleMapingsController(); 
        #endregion

        public static int iLockTime = 60;
        public static String FontString = "Arial";

        public static void LoadCurrentCompanyInfo()
        {
            CurrentCompanyInfo = (BSCompanysInfo)AppContext.CompanyCtrl.GetFirstObject();
            if (CurrentCompanyInfo == null) CurrentCompanyInfo = new BSCompanysInfo();
        }

        public static void InitModuleList()
        {
            DrillIcon = Image.FromFile(String.Format(@"{0}\Images\Drill.ico", Application.StartupPath));
            LookUpIcon = Image.FromFile(String.Format(@"{0}\Images\LookUp.ico", Application.StartupPath));
            Assembly[] assems = AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly assem in assems)
            {
                foreach (Type type in assem.GetTypes())
                {
                    if (type.IsSubclassOf(typeof(BaseModule)))
                    {
                        if (dicModuleTypes.ContainsKey(type.Name) == false)
                        {
                            dicModuleTypes.Add(type.Name, type);
                        }
                    }
                }
            }
            
        }

        public static BaseModule CreateModule(String strModuleName)
        {
            if (strModuleName.EndsWith("Module") == false)
                strModuleName = strModuleName + "Module";

            BaseModule module = null;

            if (dicModuleTypes.ContainsKey(strModuleName) == true)
            {
                module = (BaseModule)Activator.CreateInstance(dicModuleTypes[strModuleName]);
            }

            return module;
        }

        public static int OpenModule(String strModuleName, int iMainObjectID, ActionType type, bool isShowDialog)
        {
            int iObjID = 0;
            BaseModule module = CreateModule(strModuleName);
            if (module == null) return 0;

            if (module != null)
                module.Open(AppContext.MainAppForm);

            if (iMainObjectID > 0)
                module.InvalidateMainObject(iMainObjectID);

            if (type == ActionType.Edit)
                module.ActionEdit();
            else if (type == ActionType.New)
                module.ActionNew();

            return iObjID;
        }

        public static DataTable GetDataSource(String strTableName)
        {
            DataTable dt = new DataTable();
            DataSet ds = new DataSet();
            try
            {
                ds = Host.GetDataset(strTableName);
            }
            catch (Exception ex)
            {
            }
             
            if(ds != null && ds.Tables.Count > 0)
                dt = ds.Tables[0];

            return dt;
        }

        public static String GetParentTableFromColumnName(String strColumnName)
        {
            String strTableName = String.Empty;

            String[] lstTags = strColumnName.Split('_');
            if (lstTags.Length >= 3)
                strTableName = lstTags[1];

            return strTableName;
        }

        public static DataGridViewColumn CreateGridViewColumnFromColumnName(String strColumnName)
        {
            DataGridViewColumn col = null;
            if (String.IsNullOrEmpty(strColumnName)) return col;

            String[] strColumnTags = strColumnName.Split('-');
            if (strColumnTags.Length == 0) return col;

            if (strColumnTags[0].StartsWith("FK_"))
            {
                #region ComboBox
                col = new SGVComboBoxColumn();
                col.DataPropertyName = strColumnTags[0];
                if (strColumnTags.Length >= 2)
                    col.HeaderText = strColumnTags[1];
                else
                    col.HeaderText = strColumnTags[0];

                String strParentTableName = GetParentTableFromColumnName(strColumnName);
                if (String.IsNullOrEmpty(strParentTableName) == false)
                {
                    ((SGVComboBoxColumn)col).DataSourceKeyColumn = "ID";
                    ((SGVComboBoxColumn)col).DataSourceDisplayColumn = "No";
                    ((SGVComboBoxColumn)col).DataSourceTable = strParentTableName;

                    ((SGVComboBoxColumn)col).InitDataSource();
                }

                #endregion
            }
            else if (strColumnName.ToUpper().StartsWith("IS") || strColumnName.ToUpper().EndsWith("CHECK"))
            {
                col = new DataGridViewCheckBoxColumn();
                col.DataPropertyName = strColumnTags[0];
                if (strColumnTags.Length >= 2)
                    col.HeaderText = strColumnTags[1];
                else
                    col.HeaderText = strColumnTags[0];
            }
            else if (strColumnName.ToUpper().EndsWith("PICTURE") || strColumnName.ToUpper().EndsWith("PHOTO")
                || strColumnName.ToUpper().EndsWith("IMG"))
            {
                col = new DataGridViewImageColumn();
                col.DataPropertyName = strColumnTags[0];
                if (strColumnTags.Length >= 2)
                    col.HeaderText = strColumnTags[1];
                else
                    col.HeaderText = strColumnTags[0];
            }
            else
            {
                col = new SGVTextBoxColumn();
                col.DataPropertyName = strColumnTags[0];
                if (strColumnTags.Length >= 2)
                    col.HeaderText = strColumnTags[1];
                else
                    col.HeaderText = strColumnTags[0];
            }

            return col;
        }

        public static int ShowSearchScreen(BaseModule module, String strTableName, DataTable dt, String strColumnTags, String strSearchPatern)
        {
            if (String.IsNullOrEmpty(strColumnTags)) return 0;
            if (dt == null)
            {
                BaseBusinessController Ctrl = (BaseBusinessController)BusinessFactory.CreateBusinessCtrl(strTableName + "Controller");

                String strColumns = strColumnTags.Replace('|', ',');
                String[] strColumnWheres = strColumnTags.Split('|');

                StringBuilder strWhereBuilder = new StringBuilder();
                if (strColumnWheres.Length > 0)
                    strWhereBuilder.Append(String.Format(@" {0} like N'%{1}%'", strColumnWheres[0], strSearchPatern));

                for (int i = 1; i < strColumnWheres.Length; i++)
                {
                    strWhereBuilder.Append(String.Format(@" OR {0} like N'%{1}%'", strColumnWheres[i], strSearchPatern));
                }

                String strQuery1 = String.Format(@"SELECT {0}, {1} FROM {2} 
                                        WHERE AAStatus = 'Alive'
                                        AND ({3})", AppContext.cstID, strColumns, strTableName, strWhereBuilder.ToString());

                String strQuery2 = String.Format(@"SELECT {0}, {1} FROM {2} 
                                        WHERE ({3})", AppContext.cstID, strColumns, strTableName, strWhereBuilder.ToString());

                DataSet ds = new DataSet();
                try
                {
                    ds = Ctrl.GetDataset(strQuery1);
                }
                catch (Exception)
                {
                    ds = Ctrl.GetDataset(strQuery2);
                }

                if (ds != null && ds.Tables.Count > 0)
                    dt = ds.Tables[0];
            }

            SGVSearchScreen sc = new SGVSearchScreen();
            sc.RegisterModule(module);
            sc.Init(strTableName, dt, strColumnTags);
            sc.ShowDialog();

            return sc.SelectedID;
        }

        public static void InitControlFormat(IBindingControl control)
        {
            if (String.IsNullOrEmpty(control.BindingColumn) || String.IsNullOrEmpty(control.BindingTable))
                return;

            KeyValuePair<String, int> pair = Host.sqlDbUtil.GetTypeOfColumnOnTable(control.BindingTable, control.BindingColumn);

            if (pair.Key == "float" && control is SGVTextBox)
            {
                ((SGVTextBox)control).TextAlign = HorizontalAlignment.Right;
            }


        }

        public static String GenerateNumberMaskString(char cDigitGroup, char cDecimal, int iDecimalRound, char cNegative)
        {
            String strMask = String.Empty;



            return strMask;
        }

        public static String ConvertStringToNumber(String str)
        {
            String strNumber = String.Empty;

            if (CurrentCompanyInfo == null) return str;

            int iDecimalDigitIndex = str.LastIndexOf(CurrentCompanyInfo.NumberDecimalDigit);
            float f = 0f;
            float.TryParse(str, out f);
            String strFormat = GetNumericFormat();

            strNumber = f.ToString(strFormat);

            return strNumber;

        }

        public static String GetNumericFormat()
        {
            return String.Format(@"n{0}", CurrentCompanyInfo.NumberDecimalRound); ;
        }

        public static Object GetProperty(Object obj, String strProperty)
        {
            Object objProp = null;
            try
            {
                objProp = DynamicObject.GetProperty(obj, strProperty);
                //objProp = DynamicObject.ReflectUtil.GetProperty(obj, strProperty);
            }
            catch (Exception)
            {
                return null;
            }

            return objProp;
        }

        public static void SetProperty(Object obj, String strProperty, Object value)
        {
            try
            {
               // String strField = String.Format(@"_{0}{1}", strProperty[0].ToString().ToLower(), strProperty.Substring(1, strProperty.Length-1));
                DynamicObject.SetProperty(obj, strProperty, value);
            }
            catch (Exception ex)
            {
            }

        }

        public static bool CheckEnumContain(Type enumType, String strFieldName)
        {
            bool isExist = false;

            String[] strEnums = Enum.GetNames(enumType);

            foreach (String str in strEnums)
            {
                if (str == strFieldName)
                {
                    isExist = true;
                    break;
                }
            }

            return isExist;
        }

        public static bool CheckFieldNameIsFKTxtaxCode(String strFieldName)
        {
            if (strFieldName == cstFKTaxCode)
                return true;

            return false;
        }

        public static bool CheckFieldNameIsFKProduct(String strFieldName)
        {
            if (strFieldName == cstFKProduct)
                return true;

            return false;
        }

        public static bool CheckFieldNameIsUOM(String strFieldName)
        {
            if (strFieldName == cstFKProduct)
                return true;

            return false;
        }

        public static DateTime GetServerDate()
        {
            String strQuery = String.Format(@"SELECT GETDATE()");

            DataSet ds = ProductCtrl.GetDataset(strQuery);

            if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
                return Convert.ToDateTime(ds.Tables[0].Rows[0][0]);

            return DateTime.Now;
        }

        public static void CreateLock(String strUserName, String strTable, int iObjectID)
        {
            BSObjectLocksInfo ObjectLock = new BSObjectLocksInfo();
            ObjectLock.UserName = strUserName;
            ObjectLock.TableName = strTable;
            ObjectLock.ObjectID = iObjectID;
            ObjectLock.StartLockDate = GetServerDate();
            ObjectLock.isLocked = true;
            ObjectLockCtrl.CreateObject(ObjectLock);
        }

        public static void ReleaseLock(String strUserName, String strTable, int iObjectID)
        {
            ObjectLockCtrl.ReleaseLock(strUserName, strTable, iObjectID);
        }

        public static bool CheckLock(String strTable, int iObjectID)
        {
            bool isLocked = false;
            isLocked = ObjectLockCtrl.CheckLock(strTable, iObjectID, iLockTime);
            return isLocked;
        }

        public static void UpdateProgress(int iValue)
        {
            if (MainAppForm.InvokeRequired)
            {
                MainAppForm.BeginInvoke(new MethodInvoker(delegate { ProgresBar.Value = iValue; }));
            }
        }

        public static String GenerateNo(String strModuleNo, DateTime dt)
        {
            String strObjectNo = String.Empty;
            String strPrefix = String.Empty;
            String strDate = String.Empty;
            String strSuffix = String.Empty;
            String strBegin = String.Empty;

            BSNumberConfigsInfo NumberCfg = NumberCfgCtrl.GetObject(strModuleNo);
            if (NumberCfg == null)
                return cstUnknowNo;
            try
            {
                strPrefix = NumberCfg.Prefix;
                strDate = dt.ToString(NumberCfg.DateFormat);
                strBegin =String.Empty;
                if (NumberCfg.isIncludeDate)
                    strBegin = String.Format(@"{0}{1}{2}{1}", strPrefix, NumberCfg.Separator, strDate);
                else
                    strBegin = String.Format(@"{0}{1}", strPrefix, NumberCfg.Separator);

                int iMaxSuffix = AppContext.NumberCfgCtrl.GetMaxSuffix(NumberCfg.TableName, strBegin);
                strSuffix = (iMaxSuffix + 1).ToString().PadLeft(NumberCfg.SuffixLength, '0');
                strObjectNo = String.Format(@"{0}{1}", strBegin, strSuffix); 
            }
            catch (Exception ex)
            {
                return cstUnknowNo;
            }
            

            return strObjectNo;
        }

        public static void GeteRateDateSeries(DateTime dtFrom, DateTime dtTo)
        {
            DateTime dt = dtFrom;
            while(dt <= dtTo)
            {
                BSDatesInfo DateInfo = new BSDatesInfo();
                DateInfo.Date = dt;
                DateInfo.Day = dt.Day;
                DateInfo.Month = dt.Month;
                DateInfo.Year = dt.Year;
                DateInfo.MonthName = dt.ToString("MMMM");
                DateInfo.DayOfWeek = dt.DayOfWeek.ToString();
                DateInfo.DayNumberInYear = dt.DayOfYear;
                if (DateInfo.Month <= 3)
                {
                    DateInfo.QuarterNo1 = "1";
                    DateInfo.QuarterNo2 = "I";
                }
                else if (DateInfo.Month <= 6)
                {
                    DateInfo.QuarterNo1 = "2";
                    DateInfo.QuarterNo2 = "II";
                }
                else if (DateInfo.Month <= 9)
                {
                    DateInfo.QuarterNo1 = "3";
                    DateInfo.QuarterNo2 = "III";
                }
                else
                {
                    DateInfo.QuarterNo1 = "4";
                    DateInfo.QuarterNo2 = "IV";
                }

                DateCtrl.CreateObject(DateInfo);

                dt = dt.AddDays(1);
            }
        }
        
        #region Constant
        public const String strScreenStartTag = "START";
        #endregion

    }
}
